/**
 * Alipay.com Inc. Copyright (c) 2004-2018 All Rights Reserved.
 */
package com.yeyks.controller;

import com.alibaba.fastjson.JSONObject;
import com.yeyks.base.Arguments;
import com.yeyks.dal.dao.*;
import com.yeyks.dal.domain.*;
import com.yeyks.dto.HotelCreateParam;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.ServiceException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.HotelStatus;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.service.HotelService;
import com.yeyks.service.MessageService;
import com.yeyks.util.TextValidator;
import com.yeyks.util.Utility;
import com.yeyks.dto.HotelCreateParam;
import com.yeyks.exception.PermissionInvalidException;
import com.yeyks.exception.TokenInvalidException;
import com.yeyks.model.Ajax.AjaxResponseBody;
import com.yeyks.model.em.AccountType;
import com.yeyks.model.em.HotelStatus;
import com.yeyks.model.em.ResponseStatus;
import com.yeyks.service.AccountService;
import com.yeyks.service.MessageService;
import com.yeyks.util.Utility;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 酒店相关功能接口
 * @author Beacon
 * @version $Id: HotelController.java, v 0.1 2018年07月31日 14:50 Beacon Exp $
 */
@RestController
@RequestMapping(value = "/ajax/hotel")
public class HotelController {
    private Logger logger = LoggerFactory.getLogger(HotelController.class);

    @Autowired
    HotelInfoMapper hotelInfoMapper;

    @Autowired
    AccountInfoMapper accountInfoMapper;

    @Autowired
    CompanyInfoMapper companyInfoMapper;

    @Autowired
    RoomInfoMapper roomInfoMapper;

    @Autowired
    AccountService accountService;

    @Autowired
    MessageMapper messageMapper;

    @Autowired
    MessageService messageService;
    @Autowired
    HotelService hotelService;

    /**
     * 酒店搜索接口
     * @param token
     * @param city
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/searchByAddress", method = RequestMethod.POST)
    public ResponseEntity<?> searchByAddress(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "city", defaultValue = "", required = true) String city
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            accountService.getPermission(token, "");

            List<HotelInfo> hotelInfoList = hotelInfoMapper.selectByCity(city);

            response.setBody(hotelInfoList);

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }
        return ResponseEntity.ok(response);
    }

    /**
     * 新增酒店信息
     * @param token
     * @param hotelInfo
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    public ResponseEntity<?> add(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            HotelInfo hotelInfo
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            Integer userId = accountService.token2UserId(token);

            hotelInfo.setAdminId(userId);
            hotelInfo.setIsDel(1);
            hotelInfoMapper.insertReturnId(hotelInfo);

            response.setBody(hotelInfo);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        }  catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(response);
    }

    @ApiIgnore
    @RequestMapping(value = "/mgrsetinfo", method = RequestMethod.POST)
    public ResponseEntity<?> mgrsetinfo(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "force", defaultValue = "false", required = true) Boolean force,
            @RequestParam(name = "draft", defaultValue = "false", required = true) Boolean draft,
            HotelInfo hotelInfo
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {

            Integer userId = accountService.token2UserId(token);

            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            List<HotelInfo> hotelInfoList = null;
            HotelInfo existHotelInfo = null;
//            if (accountInfo.getType() > AccountType.HotelManager) {
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            } else if (accountInfo.getType() == AccountType.CityManager) {
                hotelInfo.setAdminId(accountInfo.getId());
                hotelInfoList = accountService.searchHotelsByAdministrator(hotelInfo.getAdminId());

                if (hotelInfo.getId() == null || hotelInfo.getId() == 0) {

                } else {
                    for (HotelInfo hi : hotelInfoList) {
                        if (hi.getId().longValue() == hotelInfo.getId().longValue()) {
                            existHotelInfo = hi;
                        }
                    }

                    if (existHotelInfo == null) {
                        throw new Exception("cannot find Hotel Information");
                    }
                }

                hotelInfo.setStatus(draft ? HotelStatus.PreCheck : HotelStatus.PreSubmit);
            } else if (accountInfo.getType() == AccountType.HotelManager) {
                hotelInfo.setOperatorId(accountInfo.getId());
                hotelInfoList = accountService.searchHotelsByOperator(hotelInfo.getOperatorId());
                if (hotelInfoList != null && !hotelInfoList.isEmpty()) {
                    existHotelInfo = hotelInfoList.get(0);
                }

                // 酒店管理员不允许修改酒店提成比例
                hotelInfo.setParentTax(null);

                // 不允许 修改状态
                hotelInfo.setStatus(null);
            } else {
                // 省代与平台管理员直接审核成功
                hotelInfo.setGmtModified(new Date());

                int rec = 0;
                if (!force) {
                    rec = hotelInfoMapper.updateIfNotNullByPrimaryKey(hotelInfo);
                } else {
                    rec = hotelInfoMapper.updateByPrimaryKey(hotelInfo);
                }
                if (rec == 0) {
                    throw new Exception("Updated 0 row.");
                }

                response.setBody(rec);
                response.setCode(ResponseStatus.RS_SUCCESS.getCode());
                response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                return ResponseEntity.ok(response);
            }



            if (existHotelInfo == null) {
                hotelInfo.setGmtCreate(new Date());
                hotelInfo.setGmtModified(new Date());

                if (hotelInfo.getValid() == null) {
                    hotelInfo.setValid(true);
                }

                hotelInfoMapper.insertReturnId(hotelInfo);
            } else {
                HotelInfo origHotelInfo = existHotelInfo;

                hotelInfo.setId(origHotelInfo.getId());
                hotelInfo.setGmtModified(new Date());

                if (!force) {
                    hotelInfoMapper.updateIfNotNullByPrimaryKey(hotelInfo);
                } else {
                    hotelInfoMapper.updateByPrimaryKey(hotelInfo);
                }
            }

            response.setBody(hotelInfo);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 根据一定的条件查询酒店信息
     * @param token
     * @param status
     * @param type
     * @param starLevel
     * @param gmtModifiedStart
     * @param gmtModifiedEnd
     * @param keyword
     * @param pageNum
     * @param pageSize
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/list", method = RequestMethod.POST)
    public ResponseEntity<?> list(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "status", defaultValue = "", required = true) String status,
            @RequestParam(name = "type", defaultValue = "", required = true) Integer type,
            @RequestParam(name = "starLevel", defaultValue = "", required = true) Integer starLevel,
            @RequestParam(name = "gmtModifiedStart", defaultValue = "", required = true) Long gmtModifiedStart,
            @RequestParam(name = "gmtModifiedEnd", defaultValue = "", required = true) Long gmtModifiedEnd,
            @RequestParam(name = "keyword", defaultValue = "", required = true) String keyword,
            @RequestParam(name = "pageNum", defaultValue = "", required = true) Integer pageNum,
            @RequestParam(name = "pageSize", defaultValue = "", required = true) Integer pageSize
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() >= AccountType.HotelManager) {
                throw new PermissionInvalidException();
            } else if (accountInfo.getType() == AccountType.CityManager ||
                    accountInfo.getType() == AccountType.CityAgent ||
                    accountInfo.getType() == AccountType.BranchManager ||
                    accountInfo.getType() == AccountType.Administrator) {

                List<Integer> statusList = Utility.str2intList(status);

                List<Integer> adminIds = null;
                if (accountInfo.getType() == AccountType.CityManager) {
                    adminIds = new ArrayList<>();
                    adminIds.add(accountInfo.getId());
                } else if (accountInfo.getType() == AccountType.BranchManager) {
                    adminIds = new ArrayList<>();

                    List<AccountInfo> accountInfos = accountInfoMapper.selectTwoChildren(accountInfo.getId());
                    for (AccountInfo ai : accountInfos) {
                        adminIds.add(ai.getId());
                    }
                } else if (accountInfo.getType() == AccountType.CityAgent) {
                    adminIds = new ArrayList<>();
                    List<Integer> ids = new ArrayList<>();
                    ids.add(accountInfo.getId());
                    List<AccountInfo> accountInfos = accountInfoMapper.selectChildren(ids);
                    for (AccountInfo ai : accountInfos) {
                        adminIds.add(ai.getId());
                    }
                }

                List<Map> hotelInfos = hotelInfoMapper.selectByFiltersEx(
                        adminIds, statusList, type, starLevel,
                        gmtModifiedStart == null ? null : new Date(gmtModifiedStart),
                        gmtModifiedEnd == null ? null : new Date(gmtModifiedEnd),
                        (keyword != null && !keyword.isEmpty()) ? keyword : null,
                        (pageNum != null && pageSize != null) ? (pageNum - 1) * pageSize : null, pageSize, accountInfo.getType());
                int count = hotelInfoMapper.selectByFiltersExCount(
                        adminIds, statusList, type, starLevel,
                        gmtModifiedStart == null ? null : new Date(gmtModifiedStart),
                        gmtModifiedEnd == null ? null : new Date(gmtModifiedEnd),
                        (keyword != null && !keyword.isEmpty()) ? keyword : null, accountInfo.getType());

                response.addMapBody("hotels", hotelInfos);
                response.addMapBody("count", count);
                response.setCode(ResponseStatus.RS_SUCCESS.getCode());
                response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(response);
    }

    @ApiIgnore
    @RequestMapping(value = "/getRecommand", method = RequestMethod.POST)
    public ResponseEntity<?> getRecommand(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "cityname", defaultValue = "", required = true) String cityname,
            @RequestParam(name = "checkin", defaultValue = "0", required = true) Long checkin,
            @RequestParam(name = "checkout", defaultValue = "0", required = true) Long checkout
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);

            if (cityname.isEmpty()) {
                response.setCode(ResponseStatus.RS_FAIL_INVALID_PARAMETERS.getCode());
                response.setMsg(ResponseStatus.RS_FAIL_INVALID_PARAMETERS.getMsg());
            } else {
                Date checkInDate = (checkin == 0 ? null : new Date(checkin));
                Date checkOutDate = (checkout == 0 ? null : new Date(checkout));

            }

        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(response);
    }

    @ApiIgnore
    @RequestMapping(value = "/del", method = RequestMethod.POST)
    public ResponseEntity<?> del(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            HotelInfo hotelInfo
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
//            if (accountInfo.getType() >= AccountType.HotelManager) {
            if (accountInfo.getType() == AccountType.HotelManager
                    || accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

//            int deleted = hotelInfoMapper.deleteByPrimaryKey(hotelInfo.getId());
            int deleted = hotelService.deleteById(hotelInfo.getId(), 0);
            if (deleted == 0) {
                throw new Exception("deleted 0 row!");
            }
            //查询酒店该酒店账户，将酒店账户置为停用
            HotelInfo exist = hotelInfoMapper.selectByPrimaryKey(hotelInfo.getId());
            if (exist == null) {
                throw new ServiceException("该酒店不存在");
            }
            AccountInfo existAccount = accountInfoMapper.selectByPrimaryKey(exist.getOperatorId());
            if (existAccount.getValid()) {
                existAccount.setValid(false);
                accountInfoMapper.updateByPrimaryKey(existAccount);
            }

            response.setBody(deleted);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        }

        return ResponseEntity.ok(response);
    }

    private void getMoreInfo(HotelInfo hotelInfo, AjaxResponseBody responseBody) {
        try {
            CompanyInfo companyInfo = companyInfoMapper.selectByPrimaryKey(hotelInfo.getCompanyId());
            responseBody.addMapBody("company_info", companyInfo);
        } catch (Throwable e) {
            logger.warn("获取酒店对应公司信息失败", e);
        }
        try {
            List<RoomInfo> roomInfos = roomInfoMapper.selectByHotelId(hotelInfo.getId());
            responseBody.addMapBody("room_infos", roomInfos);
        } catch (Throwable e) {
            logger.warn("获取酒店对应房间列表信息失败", e);
        }

        try {
            AccountInfo cityMgrAccountInfo = accountInfoMapper.selectByPrimaryKey(hotelInfo.getAdminId());
            responseBody.addMapBody("city_mgr", cityMgrAccountInfo);

            try {
                AccountInfo branchAccountInfo = accountInfoMapper.selectByPrimaryKey(cityMgrAccountInfo.getParentId());
                responseBody.addMapBody("branch_mgr", branchAccountInfo);
            } catch (Throwable e) {
                logger.warn("获取酒店对应分管账户信息失败", e);
            }

        } catch (Throwable e) {
            logger.warn("获取酒店对应城市运营商信息失败", e);
        }

        try {
            AccountInfo hotelAccountInfo = accountInfoMapper.selectByPrimaryKey(hotelInfo.getOperatorId());
            responseBody.addMapBody("hotel_mgr", hotelAccountInfo);
        } catch (Throwable e) {
            logger.warn("获取酒店对应账户信息失败", e);
        }
    }

    /**
     * 通过酒店id查询酒店的相关信息
     * @param request
     * @param response
     * @param token
     * @param id
     * @param all
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/mgrgetinfo", method = RequestMethod.POST)
    public ResponseEntity<?> mgrgetinfo(
            HttpServletRequest request, HttpServletResponse response,
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "id", defaultValue = "", required = true) Integer id,
            @RequestParam(name = "all", defaultValue = "", required = true) Boolean all
    ){
        AjaxResponseBody responseBody = new AjaxResponseBody();

        try {
            boolean isHotelMgr = false;
            try {
                AccountInfo accountInfo = accountService.token2AccountInfo(token);
                isHotelMgr = (accountInfo.getType() == AccountType.HotelManager);
            } catch (Throwable e) {}

            if (isHotelMgr && (id == null || id == 0)) {
                // 酒店管理员获得自己的酒店信息
                List<HotelInfo> hotelInfoList = accountService.searchHotelsByOperator(token);
                if (hotelInfoList == null || hotelInfoList.size() == 0) {
                    responseBody.setCode(ResponseStatus.RS_HOTEL_NOT_EXIST.getCode());
                    responseBody.setMsg(ResponseStatus.RS_HOTEL_NOT_EXIST.getMsg());
                } else {
                    HotelInfo hotelInfo = hotelInfoList.get(0);
                    responseBody.addMapBody("hotel_info", hotelInfo);

                    if (all != null && all) {
                        getMoreInfo(hotelInfo, responseBody);
                    }

                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                }
            } else if (id != null && id != 0) {
                // 其它管理员可以获得任意酒店信息
                HotelInfo hotelInfo = hotelInfoMapper.selectByPrimaryKey(id);
                if (hotelInfo == null) {
                    responseBody.setCode(ResponseStatus.RS_HOTEL_NOT_EXIST.getCode());
                    responseBody.setMsg(ResponseStatus.RS_HOTEL_NOT_EXIST.getMsg());
                } else {
                    responseBody.addMapBody("hotel_info", hotelInfo);

                    if (all != null && all) {
                        getMoreInfo(hotelInfo, responseBody);
                    }

                    responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                    responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
                }
            } else {
                responseBody.setCode(ResponseStatus.RS_SUCCESS.getCode());
                responseBody.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
            }
        } catch (Throwable e) {
            responseBody.setCode(ResponseStatus.RS_FAIL.getCode());
            responseBody.setMsg(ResponseStatus.RS_FAIL.getMsg());
        }

        return ResponseEntity.ok(responseBody);
    }

    /**
     * 酒店房间审核是否通过
     * @param token
     * @param hotelId
     * @param pass
     * @param comment
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/adminAudit", method = RequestMethod.POST)
    public ResponseEntity<?> adminAudit(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId,
            @RequestParam(name = "pass", defaultValue = "true", required = true) Boolean pass,
            @RequestParam(name = "comment", defaultValue = "", required = true) String comment

    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.Administrator &&
                    accountInfo.getType() != AccountType.BranchManager &&
                    accountInfo.getType() != AccountType.CityAgent) {
                throw new PermissionInvalidException();
            }

            HotelInfo hotelInfo = hotelInfoMapper.selectByPrimaryKey(hotelId);
            if (hotelInfo == null) {
                throw new Exception("cannot find hotel information.");
            }
            else if (hotelInfo.getStatus() != HotelStatus.PreCheck) {
                throw new Exception("hotel status is not precheck.");
            }

            if (!pass) {
                hotelInfo.setExtraInfo(Utility.setExtraInfo(hotelInfo.getExtraInfo(), "nopass_comment", comment));
            }

            List<Integer> ids = new ArrayList<>();
            ids.add(hotelId);
            int res = hotelInfoMapper.updateStatusByIds(ids,
                    pass ? HotelStatus.Pass : HotelStatus.NoPass,
                    hotelInfo.getExtraInfo());

            if (res == 0) {
                throw new Exception("update 0 rows");
            } else if (pass) {
                messageService.passHotelInfo(hotelInfo);
            } else if (!pass) {
                messageService.nopassHotelInfo(hotelInfo);
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 酒店是否启用
     * @param token
     * @param hotelId
     * @param valid
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/adminValid", method = RequestMethod.POST)
    public ResponseEntity<?> adminAudit(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "hotelId", defaultValue = "", required = true) Integer hotelId,
            @RequestParam(name = "valid", defaultValue = "true", required = true) Boolean valid
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.Administrator &&
                    accountInfo.getType() != AccountType.BranchManager &&
                    accountInfo.getType() != AccountType.CityAgent) {
                throw new PermissionInvalidException();
            }

            List<Integer> ids = new ArrayList<>();
            ids.add(hotelId);
            int res = hotelInfoMapper.updateValidByIds(ids, valid);

            if (res == 0) {
                throw new Exception("update 0 rows");
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }


    @ApiIgnore
    @RequestMapping(value = "/setPayAccounts", method = RequestMethod.POST)
    public ResponseEntity<?> setPayAccounts(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "alipay", defaultValue = "", required = true) String alipay,
            @RequestParam(name = "wxpay", defaultValue = "", required = true) String wxpay
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            Map<String, String> payAccounts = new HashMap<>();
            payAccounts.put("alipay", alipay);
            payAccounts.put("wxpay", wxpay);

            String extraInfo = Utility.setExtraInfo(accountInfo.getExtraInfo(), "pay_accounts", payAccounts);
            int rec = accountInfoMapper.updateExtraInfoById(accountInfo.getId(), extraInfo);

            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    @ApiIgnore
    @RequestMapping(value = "/getPayAccounts", method = RequestMethod.POST)
    public ResponseEntity<?> getPayAccounts(
            @RequestParam(name = "token", defaultValue = "", required = true) String token
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() == AccountType.User) {
                throw new PermissionInvalidException();
            }

            response.setBody(Utility.getExtraInfo(accountInfo.getExtraInfo(), "pay_accounts"));
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 查询指定条件下代理商的酒店数量
     * @param token
     * @param dtStart
     * @param dtEnd
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/getNewCount", method = RequestMethod.POST)
    public ResponseEntity<?> getNewCount(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "dtStart", defaultValue = "0", required = true) Long dtStart,
            @RequestParam(name = "dtEnd", defaultValue = "0", required = true) Long dtEnd
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            int count = 0;
            if (accountInfo.getType() == AccountType.Administrator) {
                count = hotelInfoMapper.countByAdminIds(null, new Date(dtStart), new Date(dtEnd));
            } else if (accountInfo.getType() == AccountType.BranchManager
                    || accountInfo.getType() == AccountType.CityAgent) {
                List<Integer> branchIds = new ArrayList<>();
                branchIds.add(accountInfo.getId());
                List<AccountInfo> accountInfos = accountInfoMapper.selectChildren(branchIds);
                List<Integer> cityIds = new ArrayList<>();
                for (AccountInfo info : accountInfos) {
                    cityIds.add(info.getId());
                }
                count = hotelInfoMapper.countByAdminIds(cityIds, new Date(dtStart), new Date(dtEnd));
            } else if (accountInfo.getType() == AccountType.CityManager) {
                List<Integer> cityIds = new ArrayList<>();
                cityIds.add(accountInfo.getId());
                count = hotelInfoMapper.countByAdminIds(cityIds, new Date(dtStart), new Date(dtEnd));
            }

            response.setBody(count);
            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 修改酒店的extro信息
     * @param token
     * @param checkinTime
     * @param checkoutTime
     * @param extraNote
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/mgrSetCheckRule", method = RequestMethod.POST)
    public ResponseEntity<?> mgrSetCheckRule(
            @RequestParam(name = "token", defaultValue = "", required = true) String token,
            @RequestParam(name = "checkinTime", defaultValue = "", required = true) String checkinTime,
            @RequestParam(name = "checkoutTime", defaultValue = "", required = true) String checkoutTime,
            @RequestParam(name = "extraNote", defaultValue = "", required = true) String extraNote
    ){
        AjaxResponseBody response = new AjaxResponseBody();

        try {
            AccountInfo accountInfo = accountService.token2AccountInfo(token);
            if (accountInfo.getType() != AccountType.HotelManager) {
                throw new PermissionInvalidException();
            }

            List<HotelInfo> hotelInfos = accountService.searchHotelsByOperator(accountInfo.getId());
            if (hotelInfos == null || hotelInfos.size() == 0) {
                throw new Exception("no hotel information");
            }

            HotelInfo hotelInfo = hotelInfos.get(0);

            JSONObject extraObject = Utility.toJsonObject(hotelInfo.getExtraInfo());
            if (extraObject == null) {
                throw new Exception("get hotel extra information failed");
            }

            extraObject.put("checkinTime", checkinTime);
            extraObject.put("checkoutTime", checkoutTime);
            extraObject.put("extraNote", extraNote);

            HotelInfo updateHotelInfo = new HotelInfo();
            updateHotelInfo.setId(hotelInfo.getId());
            updateHotelInfo.setExtraInfo(extraObject.toJSONString());

            hotelInfo.setExtraInfo(extraObject.toJSONString());
            int rec = hotelInfoMapper.updateIfNotNullByPrimaryKey(updateHotelInfo);
            if (rec == 0) {
                throw new Exception("updated 0 row.");
            }

            response.setCode(ResponseStatus.RS_SUCCESS.getCode());
            response.setMsg(ResponseStatus.RS_SUCCESS.getMsg());
        } catch (TokenInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_TOKEN.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_TOKEN.getMsg());
        } catch (PermissionInvalidException e) {
            response.setCode(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_INVALID_PERMISSION.getMsg());
        } catch (DuplicateKeyException e) {
            response.setCode(ResponseStatus.RS_FAIL_DUPLICATE.getCode());
            response.setMsg(ResponseStatus.RS_FAIL_DUPLICATE.getMsg());
        } catch (Throwable e) {
            response.setCode(ResponseStatus.RS_FAIL.getCode());
            response.setMsg(e.getMessage());
        }

        return ResponseEntity.ok(response);
    }

    /**
     * 新增酒店(同时需要先增加公司信息，再增加用户，后增加酒店)
     *
     * @param token
     * @param createParam
     * @return
     */
    @ApiIgnore
    @RequestMapping(value = "/addV2", method = RequestMethod.POST)
    public ResponseEntity<?> addV2(@RequestParam(name = "token") String token, HotelCreateParam createParam) {
        checkParam(token, createParam.getPhone(), createParam.getPassword(), createParam.getUsername());
        //首先增加公司信息company
        AccountInfo accountInfo = accountService.token2AccountInfoV2(token);
        if (accountInfo.getType() == null || (accountInfo.getType() != null && !accountInfo.getType().equals(AccountType.CityManager))) {
            throw new ServiceException("当前操作人非法");
        }
        hotelService.createHotel(createParam, accountInfo.getId());

        return ResponseEntity.ok(AjaxResponseBody.success());
    }

    private void checkParam(String token, String phone, String password, String username) {
        if (Arguments.isEmpty(token)) {
            throw new ServiceException("token不能为空");
        }
        if (Arguments.isEmpty(phone)) {
            throw new ServiceException("商家手机号输入为空");
        }
        if (!TextValidator.MOBILE.boolCheck(phone)) {
            throw new ServiceException("商家手机号格式有误");
        }
        if (Arguments.isEmpty(username)) {
            throw new ServiceException("用户名不能为空");
        }
        if (Arguments.isEmpty(password)) {
            throw new ServiceException("输入密码不能为空");
        }
        if (password.length() < 6 || password.length() > 16) {
            throw new ServiceException("密码的有效长度为6-16位");
        }
    }
}